<?php

require_once PATH_FFWD.'core/baseobject.class.php';
require_once PATH_FFWD.'core/baseuser.class.php';
require_once PATH_FFWD.'prototypes/module.base.php';
require_once PATH_FFWD.'core/database.class.php';
require_once PATH_FFWD.'core/html_helpers.php';

define('ESCAPED_FRAGMENT','_escaped_fragment_');
define('BYHASHCHANGE','_hashchange_');
define('LAST_PAGE_URL','__last_page_url');
define('JAVASCRIPT_HISTORY_BACK','js_hstry_bck');

class BaseApplication extends BaseObject{
	public $controller=0;
	protected $metas=Array();
	protected $scripts=Array();
	protected $csses=Array();
	protected $redirected=0;
	protected $blockRedirect=0;
	protected $user=0;
	protected $dbo=0;
	protected $noframe=0;
	public    $lang='hu';
	public 	  $charset='UTF-8';
	protected $saveresponse=1;
	public function __construct($p){
		$this->controller=&$this;//compatibility
		if(!isset($p['name']))throw new Exception('application_name_not_defined');
		$this->dbo=&$GLOBALS['db'];
		$this->name=$p['name'];
		$this->user=new User($this->dbo);
		$GLOBALS['user']=&$this->user;
		/**/
		$this->addCSS('default');
		$this->addCSS('jquery_ui');
		$this->addCSS('global');
		$this->addJS('jquery');
		$this->addJS('jquery_ui');
		$this->addJS('jquery_ui_hu');
		$this->addJS('jquery_watermarkinput');
		$this->addJS('swfobject');		
		$this->addJS('common');/**/
	}
	
	public function __destruct(){
		if(CLI)exit;
		if(!$this->redirected){
			if(isset($this->user->storage[LAST_PAGE_URL]) && $this->user->storage[LAST_PAGE_URL]==$_SERVER['REQUEST_URI'])return;
			$this->user->storage[LAST_PAGE_URL]=$_SERVER['REQUEST_URI'];
		}
	}
	
	public function noframe(){
		$this->noframe=1;
		while(ob_get_level())ob_end_clean();
	}
	

	
	public function createModule($fn){
		if(!file_exists($fn))throw new Exception('File not found:'.$fn);
		require_once $fn;
		try{			
			$m=strrpos($fn,'/');
			$modulename=substr($fn,$m+8,-4).'Module';
			return new $modulename($modulename);
		}catch(Exception $e){
			//throw new Exception('cannot create module:'.substr($modulename,0,-6));
			throw new Exception($e);
			return REFNULL;
		}
	}
	
	public function executeModule_hash($data=0){
		if(!isset($data[MODULE]))throw new Exception('$data[MODULE] not set');
		if(!isset($data[ACTION]))throw new Exception('$data[ACTION] not set');
		ob_start();
		$module=&$this->createModule($data[MODULE]);
		if(!$module)throw new Exception('Module cannot be created:'.$data[MODULE]);
		$action=$data[ACTION].'Action';
		if($main)ob_start();
		$content='';
		try{
			$r=$module->$action($data);
		}catch(Exception $e){
			obflush();
			if(0 && strpos($e->getMessage(), 'method does not exist')){
				//throw new Exception('action does not exist: '.$action);
			}else
				throw new Exception($e);
		}/**/
		if($main){
			$content=ob_get_contents();		
			ob_end_clean();		
		};
		return $content;			
	}
	
	public function executeModule($data=0,$main=0){
		if(!isset($data[MODULE]))throw new Exception('$data[MODULE] not set');
		if(!isset($data[ACTION]))throw new Exception('$data[ACTION] not set');
		ob_start();
		$module=&$this->createModule(get_module_filename($data));
		if(!$module)throw new Exception('Module cannot be created:'.$data[MODULE]);
		$action=$data[ACTION].'Action';
		if($main){			
			$data=array_merge($_POST,$data);
			ob_start();
		}
		$content='';
		try{
			$r=$module->$action($data);
		}catch(Exception $e){
			obflush();
			if(0 && strpos($e->getMessage(), 'method does not exist'))
				throw new Exception('action does not exist: '.$action);
			else
				throw new Exception($e);
		}/**/
		if($main){
			$content=ob_get_contents();		
			ob_end_clean();		
		};
		return $content;		
	}
	
	public function sendAjaxHeaders(){
		$this->sendUTF8HTMLHeader();
	}
	
	public function execute($data=0){
		if(is_array($data)){
			$this->blockRedirect=1;
			$this->executeModule($data);
			$this->blockRedirect=0;
		}
		else
		if(is_string($data)){
			$data=parse_url($data);
			print_var($data);
		}else
		if($data==1){
			$content=$this->executeModule(array_merge($_SERVER['REQUEST_DATA'],$_POST),1);		
			$this->sendUTF8HTMLHeader();
			global $app,$db;
			
			if($this->noframe && 0){
				echo $content;
				$this->shutdown();
			}
			$fn=PATH_APPS.strtolower($this->__get('name')).'/templates/layout.php';
			if(!is_dir(dirname($fn))){
				mkdir(dirname($fn),0766,1);
			}
			if(!file_exists($fn)){
				file_put_contents($fn, file_get_contents(PATH_FFWD.'defaulttemplates/layout.php'));
				chmod($fn,0766);
				throw new Exception('Layout template did not exist, generated: '.$fn);
			}
			include $fn;
		}else{
			throw new Exception('BaseApplication::execute($data) cannot be called without parameters');			
		}	
	}
	
	public function sendUTF8HTMLHeader(){
		if(headers_sent()){
			console_log('!cannot modify header information, headers already sent');
			return;
		}	
		header('Content-type:text/html; charset='.$this->charset);	
	}	
	
	/*
	 * Prints <meta> tags stored previously
	 */
	
	public function printMetas(){
		foreach($this->metas as $k=>$v)echo "<meta name='$k' content='$v' >\n";
	}
	
	/*
	 * print <script> including tags
	 */
	
	public function linkExternalJS(){
		foreach($this->scripts as $script)echo "<script type='text/javascript' src='".LOCATION_ROOT."/js/$script.js?s=".rand(0,99999)."' ></script>\n";
	}
	
	public function linkExternalCSS(){
		foreach($this->csses as $css)echo "<link rel='stylesheet' type='text/css' href='".LOCATION_ROOT."/css/$css.css' />\n";
		
	}
	
	
	/*
	 * Stores a meta variable
	 * @param0: name attribute of the meta tag
	 * @param1: content attribute of the meta tag
	 */
	
	public function addMeta($name,$content){
		$this->metas[$name]=$content;
	}
	
	public function addJS($script){
		$this->scripts[$script]=$script;
	}
	
	public function addCSS($css){
		$this->csses[$css]=$css;
	}
	
	public function link($fn,$type){
		if($type=='css')$this->addCSS($fn);
		else if($type=='js')$this->addJS($fn);
	}
	
	public function &obflush(){
		while(ob_get_level())ob_end_flush();
		return $this;
	}
	
	public function redirectLast($change=Array()){		
		if(isset($this->user->storage[LAST_PAGE_URL])){
			$last=$this->user->storage[LAST_PAGE_URL];
			$last=changeurlkey($last,$change);
			$this->redirectTo($last);
		}else{
			if(!empty($change))throw new Exception('not implemented');
			$this->redirectTo(JAVASCRIPT_HISTORY_BACK);
		}
	}
	
	public function shutdown(){
		$this->redirected=1;
		exit;
	}
	
	public function redirectTo($url){		
		if($this->blockRedirect)return;
		if(is_array($url))$url=link_for($url);
		if(is_array($url))$url=link_for($url);
		$this->redirected=1;
		if(headers_sent() || $url==JAVASCRIPT_HISTORY_BACK){
				echo "<script type='text/javascript'>";
				//echo "//";
				if($url==JAVASCRIPT_HISTORY_BACK){
					echo "history.back();";
				}else{
					echo "document.location.assign('$url');";
				};
				echo "</script>";
				$this->shutdown();
				return;
		}
		$debug=DEBUG;
		//while(ob_get_level())ob_end_clean();
		echo "redirect";
		if(!$debug){				
			try{
				header_redirect($url,303);
			}catch(Exception $e){$debug=1;}
		};
		if($debug){
			obflush();
			echo "<center><h3><a href='$url'>BaseApplication::redirectTo($url)</a></h3><center>";
		}			
		$this->shutdown();
	}
}
